/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package shooter;

import com.jme3.app.SimpleApplication;
import com.jme3.app.state.AbstractAppState;
import com.jme3.asset.AssetManager;
import com.jme3.bullet.BulletAppState;
import com.jme3.collision.CollisionResult;
import com.jme3.collision.CollisionResults;
import com.jme3.input.*;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Ray;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.*;
import com.jme3.scene.*;
import com.jme3.scene.shape.Sphere;
import java.util.ArrayList;
import snails.*;

/**
 *
 * @author ulfgur
 */
public class CannonAppState extends AbstractAppState
{
    //everything that has to do with the application as a whole
    AssetManager assetManager;
    Node rootNode;
    ViewPort viewPort;
    BulletAppState physics;
    SimpleApplication app;
    InputManager inputManager;
    ChaseCamera chaseCam;
    CameraNode camNode;
    FlyByCamera flycam;
    Camera cam;
    
    
    //Centralised node where EVERYTHING in this app state is stored, for easy attaching and detaching.
    private Node cannonNode;
    
    private Snail currentSnail;
    
    
    public CannonAppState(SimpleApplication app)
    {
        setUp(app);
        cannonNode = new Node();
    }
    
    
    /**
     * sets things up so that we can acess
     * all app assets directly.
     * @param app 
     */
    private void setUp(SimpleApplication app)
    {
        this.app = app;
        assetManager = app.getAssetManager();
        rootNode = app.getRootNode();
        viewPort = app.getViewPort();
        cam = app.getCamera();
        inputManager = app.getInputManager();
        flycam = app.getFlyByCamera();
    }
    
    public void setSnail(Snail s)
    {
        currentSnail = s;
        
        cannonNode.detachAllChildren();
            Sphere playerMesh = new Sphere(20, 20, 5);
            Geometry playerGeom = new Geometry("player", playerMesh);
            Material playerMat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
            playerMat.setColor("Color", ColorRGBA.Blue);
            playerGeom.setMaterial(playerMat);
            cannonNode.attachChild(playerGeom);
            
            
            chaseCam = new ChaseCamera(cam, cannonNode, inputManager);
            chaseCam.setDragToRotate(true);
            chaseCam.setMaxDistance(100);
            chaseCam.setInvertVerticalAxis(true);
            chaseCam.setInvertHorizontalAxis(false);
            chaseCam.setSmoothMotion(true);
            chaseCam.setToggleRotationTrigger(new MouseButtonTrigger(MouseInput.BUTTON_RIGHT));
            
            
         ArrayList<CannonBay> cannonBays = currentSnail.getCannons();
         
         for(CannonBay bay : cannonBays)
         {
             ArrayList<Cannon> cannons = bay.getCannons();
             for(Cannon cannon : cannons)
             {
                 Node n = new Node();
                 n.setLocalTranslation(bay.getPos());
                 n.addControl(new CannonDragControl(n, cannon));
                 cannonNode.attachChild(n);
             }
             
         }
         initKeys();
    }
    
    
        private void initKeys()
        {
          //TODO: figure out how to map oh, say, the RMB to cam movements.
            // You can map one or several inputs to one named action
            inputManager.addMapping("DragCannon",  new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
            
            
            
            enableDragKeys();
      }
        
     /**
     * enables keys
     */
    public void enableDragKeys()
    {
        inputManager.addListener(mainListener,"DragCannon");
    }
    
    
      boolean rotateCannons = false;
      CannonDragControl applied = null;
      /**
       * responds to input
       */
      private ActionListener mainListener = new ActionListener()
      {
            public void onAction(String name, boolean keyPressed, float tpf)
            {
                if (name.equals("DragCannon") && keyPressed)
                {
                    CollisionResults results = new CollisionResults();
                    
                    // Convert screen click to 3d position
                    Vector2f click2d = inputManager.getCursorPosition();
                    Vector3f startAim = cam.getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 0f).clone();
                    Vector3f dir = cam.getWorldCoordinates(new Vector2f(click2d.x, click2d.y), 1f).subtractLocal(startAim).normalizeLocal();
                    
                    Ray ray = new Ray(startAim, dir);
                    rootNode.collideWith(ray, results);
                    if(results.size() > 0)
                    {
                        for(CollisionResult result : results)
                        {
                            CannonDragControl cont = result.getGeometry().getParent().getControl(CannonDragControl.class);
                            if(cont != null)
                            {
                                applied = cont;
                                break;
                            }
                        }
                        
                    }
                    rotateCannons = true;
                }
                if(name.equals("DragCannon") && !keyPressed)
                {
                   rotateCannons = false;
                }
            }
      };
    
    
    
    
    @Override
    public void setEnabled(boolean enabled)
    {
      super.setEnabled(enabled);
      if(enabled)
      {
          if(cannonNode != null)
          {
              rootNode.attachChild(cannonNode);
          }
      }else
      {
          if(cannonNode != null)
          {
              rootNode.detachChild(cannonNode);
          }
      }
    }
    
    
    
    @Override
    public void update(float tpf)
    {
        if(rotateCannons)
        {
            applied.rotate(tpf);
        }
    }
}
